﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.IO;
using System.Threading;
using RTree;
using Rectangle = RTree.Rectangle;
using Size = System.Windows.Size;


namespace CartoGraphic.Util
{
    public partial class QuadTreeForm : Form
    {
        QuadTree<MyPoint> quadTree;
        Graphics g;
        List<MyPoint> points = null;
        List<MyPoint> selectedPoints;
        Brush brush1, brush2;
        private PointF m_Last;
        private PointF m_DownLoc;
        int mode = 0;
        private RTree<string> Instance { get; set; }

        public QuadTreeForm()
        {
            InitializeComponent();
            quadTree = new QuadTree<MyPoint>(new Size(80, 80), 0, true);
            g = this.CreateGraphics();
            brush1 = new SolidBrush(Color.Black);
            brush2 = new SolidBrush(Color.Red);
            selectedPoints = new List<MyPoint>();
        }

        private void  thread()
        {
            
                
            
            
        }

        private void openWithRtree()
        {
            try
            {
                points = new List<MyPoint>();
                Instance = new RTree<string>();
                Instance.Add(new Rectangle(0, 0, 1, 1, 0, 0), "Origin");
                Instance.Add(new Rectangle(1, 1, 0, 0, 0, 0), "Box1");
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Title = "选择随机点";
                dlg.Filter = "csv(*.csv)|*.csv";
                dlg.ShowDialog();
                StreamReader sr = new StreamReader(@dlg.FileName, Encoding.GetEncoding("gb2312"));
                string sFile = sr.ReadToEnd();
                string[] vals = sFile.Split('\n');
                for (int i = 1; i < vals.Length; i++)
                {
                    string sLine = vals[i];
                    if (sLine.Contains(",") == false)
                        continue;
                    string[] sVal = sLine.Split(',');
                    double x = Convert.ToDouble(sVal[1]) * 1300;
                    double y = Convert.ToDouble(sVal[2]) * 700;
                    float x_f = (float)x;
                    float y_f = (float)y;
                    Instance.Add(new Rectangle(x_f, y_f, x_f + 1, y_f + 1, 0, 0), "" + x_f + "," + y_f);
                    MyPoint point = new MyPoint(x, y);
                    points.Add(point);
                    quadTree.Insert(point);
                }
                points = quadTree.Query(new Rect(g.ClipBounds.X, g.ClipBounds.Y, g.ClipBounds.Width, g.ClipBounds.Height));
                foreach (MyPoint point in points)
                {
                    g.FillEllipse(brush1, (float)point.rect.X, (float)point.rect.Y, (float)point.rect.Width, (float)point.rect.Height);
                }
                MessageBox.Show("共读取" + points.Count + "个点.");
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            
        }

        private void 读取ToolStripMenuItem_Click(object sender, EventArgs e)
        {
           openWithRtree();
              
            //OpenFileDialog dlg = new OpenFileDialog();
            //dlg.Title = "选择随机点";
            //dlg.Filter = "csv(*.csv)|*.csv";
            //dlg.ShowDialog();
            //StreamReader sr = new StreamReader(@dlg.FileName, Encoding.GetEncoding("gb2312"));
            //string sFile = sr.ReadToEnd();
            //string[] vals = sFile.Split('\n');
            //for (int i = 1; i < vals.Length; i++)
            //{
            //    string sLine = vals[i];
            //    if (sLine.Contains(",") == false)
            //        continue;
            //    string[] sVal = sLine.Split(',');
            //    double x = Convert.ToDouble(sVal[1]) * 1300;
            //    double y = Convert.ToDouble(sVal[2]) * 700;
            //    MyPoint point = new MyPoint(x, y);
            //    quadTree.Insert(point);
            //}
            //points = quadTree.Query(new Rect(g.ClipBounds.X, g.ClipBounds.Y, g.ClipBounds.Width, g.ClipBounds.Height));
            //foreach (MyPoint point in points)
            //{
            //    g.FillEllipse(brush1, (float)point.rect.X, (float)point.rect.Y, (float)point.rect.Width, (float)point.rect.Height);
            //}
            //MessageBox.Show("共读取" + quadTree.GetQuadObjectCount() + "个点.");
        }

        class MyPoint:IQuadObject
        {
            public double X, Y;
            public Rect rect;

            public MyPoint(double x, double y)
            {
                this.X = x;
                this.Y = y;
                rect = new Rect(x, y, 1, 1);
            }

            public event EventHandler BoundsChanged;

            public Rect Bounds
            {
                get { return rect; }
            }

        }

        private void QuadTreeForm_Paint(object sender, PaintEventArgs e)
        {
            if (points == null)
                return;
            foreach (MyPoint point in points)
            {
                e.Graphics.FillEllipse(brush1, (float)point.rect.X, (float)point.rect.Y,
                                       (float)point.rect.Width, (float)point.rect.Height);
            }
        }

        private void QuadTreeForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start(); //  开始监视代码       
                RTree.Point searchPoint = new RTree.Point(e.X, e.Y, 0);
                MyPoint searchPoint2 = new MyPoint(e.X, e.Y);
                if (mode==2)
                {

                    List<string> searchs = Instance.Nearest(searchPoint, 1);
                    if (searchs.Count > 0)
                        toolTip1.Show(searchs[0], this, new System.Drawing.Point(e.X, e.Y));
                }
                else if (mode==0)
                {
                    double mind = 100000;
                    MyPoint nearPoint = null;
                    foreach (MyPoint point in points)
                    {
                        double d = distance(point, searchPoint2);
                        if (d < mind)
                        {
                            mind = d;
                            nearPoint = point;
                        }

                    }
                    toolTip1.Show(nearPoint.X + "," + nearPoint.Y, this, new System.Drawing.Point(e.X, e.Y));
                }
                selectedPoints.Clear();
                m_DownLoc = new PointF(e.X, e.Y);
                stopwatch.Stop(); //  停止监视
                TimeSpan timeSpan = stopwatch.Elapsed;
                MessageBox.Show(timeSpan.TotalMilliseconds.ToString() + "毫秒");
            }
            else 
            {
                m_DownLoc = new PointF(e.X, e.Y);
            }
            
        }

        private void QuadTreeForm_MouseUp(object sender, MouseEventArgs e)
        {
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start(); //  开始监视代码         
            float x = Math.Min(m_DownLoc.X, m_Last.X);
            float y = Math.Min(m_DownLoc.Y, m_Last.Y);
            float w = Math.Abs(m_DownLoc.X - m_Last.X);
            float h = Math.Abs(m_DownLoc.Y - m_Last.Y);
            Rect newBounds = new Rect(x, y, w, h);
            if (mode==0)
            {
                List<MyPoint> retList2 = new List<MyPoint>();
                foreach (MyPoint point in points)
                {
                    if (newBounds.IntersectsWith(point.Bounds))
                        retList2.Add(point);
                }
                selectedPoints.AddRange(retList2);
            }
            else if(mode==1)
            {
                List<MyPoint> retList = quadTree.Query(newBounds);
                selectedPoints.AddRange(retList);
            } 
            foreach (MyPoint point in selectedPoints)
            {
                g.FillEllipse(brush2, (float)point.rect.X, (float)point.rect.Y,
                                       (float)point.rect.Width+0.5f, (float)point.rect.Height+0.5f);
            }
            stopwatch.Stop(); //  停止监视
            TimeSpan timeSpan = stopwatch.Elapsed;
            MessageBox.Show(timeSpan.TotalMilliseconds.ToString() + "毫秒");
            
        }

        private double distance(MyPoint a, MyPoint b)
        {
            return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        private void QuadTreeForm_MouseMove(object sender, MouseEventArgs e)
        {
            m_Last = e.Location;
        }

        private void 普通ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = 0;
        }

        private void 空间索引ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = 1;
        }

        private void r树ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = 2;
        }

        private void 显示时间ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
        }
    }
}
